﻿# -*- coding:utf-8 -*-
#
# views.py
# 
import datetime
from decimal import *
#
from django.conf import settings
from django.shortcuts import render_to_response
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
from django.http import HttpResponse
from django.http import HttpResponseServerError
from django.core.urlresolvers import reverse
from django.core.files.uploadhandler import FileUploadHandler
from django.template import RequestContext, Context
from django.utils import simplejson
from django.contrib.auth.decorators import login_required
from django.contrib.sessions.backends.db import SessionStore
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.contrib.auth.decorators import permission_required
from django.contrib import messages
from django.db.models import Sum, Count
from django.db import transaction
#
from house.models import Apartment
from house.models import MonthlyPayment
from house.models import Payment
from house.models import Operation  
from house.models import Variables
#
from house.forms import ArrivalForm
from house.forms import ExpenseForm
from house.forms import ApartmentForm


month_verbose = ('err','Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь',)

from homesite import get_version
version_string = get_version()

#utils

def move_month(month, year, delta):
    yd, md = divmod(month + delta - 1, 12)
    return range(1,13)[md], year + yd


def get_month_year_session(request):
    d = datetime.datetime.now()
    processed_month = int(request.session.get('processed_month',d.month))
    processed_year = int(request.session.get('processed_year', d.year))
    return processed_month, processed_year


def set_month_year_session(request, month, year):
    request.session['processed_month'] = int(month)  
    request.session['processed_year'] = int(year)
    return 


def context_processor_proc(request):
    #
    request.session["prev_request_path"] = request.path
    context_extras = {
        'version_string': version_string,
        }
    return context_extras


def render_to(request, template, context):
    d = datetime.datetime.now()
    balance_full = Operation.objects.all().aggregate(Sum("amount"))
    
    apartment_payment = Apartment.objects.exclude(summ=0).count()
    apartment_payment_priv = Apartment.objects.filter(summ=150).count()
    apartment_none_payment = Apartment.objects.filter(summ=0).count()
    
    try:
        processed_month = context['processed_month']
    except:
        processed_month = d.month
    try:
        processed_year = context['processed_year']
    except:
        processed_year = d.year
    
    mp = MonthlyPayment.objects.filter(year=processed_year, month=processed_month).aggregate(Sum("amount"))
    if mp['amount__sum'] == None:
        mp['amount__sum'] = 0
    chop = Operation.objects.filter(period_year=processed_year, period_month=processed_month, special_item='ac').aggregate(Sum("amount"))
    if chop['amount__sum'] == None:
        chop['amount__sum'] = 0
    plan_apartments = Apartment.objects.all().aggregate(Sum('summ'))['summ__sum']  
    if plan_apartments == None:
        plan_apartments = 0        
        
    plan_chop = Decimal(Variables.objects.get(name='chop').value)
    plan_concierge_fee = Decimal(Variables.objects.get(name='concierge_fee').value)
 
    qs = MonthlyPayment.objects.filter(year=processed_year, month=processed_month)
    qs.query.group_by = ['house_monthlypayment.apartment_id']
    dac = qs.annotate(monthly_summ=Sum('amount')).order_by("house_monthlypayment.apartment_id")  
    debt_apartments_count = apartment_payment
    for i in dac:
        if i.monthly_summ == i.apartment.summ:  
            debt_apartments_count = debt_apartments_count - 1
            
    # print page   
    if request.GET.has_key('print'):
        base_template = 'house/base-print.html'
        printer = True
    else:
        base_template = 'house/base.html' 
        printer = False
        
    context_extra = Context({
        'balance_full': balance_full['amount__sum'],
        'apartment_payment': apartment_payment,
        'apartment_payment_priv': apartment_payment_priv,
        'apartment_none_payment':apartment_none_payment,
        'apartment_payment_all': apartment_payment + apartment_none_payment,
        'monthly_amount': mp['amount__sum'],
        'chop_amount':chop['amount__sum'],
        'plan_concierge_fee':plan_concierge_fee,
        'plan_apartments':plan_apartments,
        'plan_chop':plan_chop,
        'plan_arrival': plan_apartments + plan_chop,
        'debt_apartments': plan_apartments - mp['amount__sum'],
        'debt_apartments_count':debt_apartments_count,
        'printing':printer,
        'base_template':base_template,
    })
    return render_to_response('house/'+template, context, context_instance=RequestContext(request, context_extra))


#views

#@method_decorator(login_required)
@login_required
@transaction.commit_manually
def index(request): 
    processed_month, processed_year = get_month_year_session(request)
    #    
    if request.method == 'POST':
        if request.POST.has_key('cash') and request.POST.has_key('id'):
            apartment = get_object_or_404(Apartment, id = request.POST['id'])
            try:
                cash = Decimal(request.POST['cash'])
            except:
                messages.warning(request, 'Требуется число.')
                return HttpResponseRedirect(reverse('index', args=[]))
            try:
                payment = Payment(apartment=apartment, amount=cash)
                payment.save()
                mdelta = 0
                while cash > 0:
                    m, y = move_month(processed_month, processed_year, mdelta)
                    concierge_fee_operation = Operation.objects.filter(period_year=y, period_month=m, special_item='ec').count()
                    monthly_summ = MonthlyPayment.objects.filter(apartment=apartment, year=y, month=m).aggregate(Sum("amount"))['amount__sum']
                    if monthly_summ == None:
                        monthly_summ = 0
                    if (cash + monthly_summ) > apartment.summ:
                        amount = apartment.summ - monthly_summ
                    else:
                        amount = cash
                    cash = cash - amount  
                    mpayment = MonthlyPayment(apartment=apartment, payment=payment, year=y, month=m, amount=amount)
                    mpayment.save()
                    if concierge_fee_operation != 0:
                        operation = Operation(kind='A',
                                              name='Долг от квартиры №%s' % apartment.number, 
                                              quantity='1', 
                                              price=amount,
                                              amount=amount, 
                                              comment='', 
                                              special_item='ad', 
                                              period_year = y, 
                                              period_month = m)
                        operation.save()
                    mdelta = mdelta + 1  
            except:    
                transaction.rollback()
                messages.warning(request, 'Ошибка в транзакции. Зачисление не произведено!')
            else:
                transaction.commit()
                messages.success(request, 'Зачислено успешно.') 
            return HttpResponseRedirect(reverse('index', args=[]))
    #
    apartment = Apartment.objects.all()
    monthlypayment = MonthlyPayment.objects.select_related().filter(year=processed_year, month=processed_month)
    apartment_id = [i.apartment.id for i in  monthlypayment] 
    apartment_list=[]
    for ap in apartment.values():
        item = dict(ap)
        if item['id'] in apartment_id: 
            item['cashed'] = True
            mp = monthlypayment.filter(apartment__id=ap['id'])
            last_data = None
            payment_summ = 0
            for mpitem in mp:
                payment_summ = payment_summ + mpitem.amount
                last_data  = mpitem.data
            if payment_summ != item['summ']:
                item['cashed'] = False   
            item['cashed_date'] = last_data
            item['payment_list'] = mp
            item['payment_summ'] = payment_summ
        else:
            item['cashed'] = False
            item['cashed_date'] = None
            item['payment_list'] = None
        apartment_list.append(item)
    
    context = Context({
        'apartment_list': apartment_list,
        'processed_month_verbose': month_verbose[processed_month],
        'processed_month': processed_month,
        'processed_year': processed_year,
    })
    return render_to(request, 'index-col.html', context)



def prev_month(request):
    m, y = get_month_year_session(request)
    nm, ny =  move_month(m, y, -1)
    set_month_year_session(request, nm, ny)
    return HttpResponseRedirect(reverse('index', args=[]))



def next_month(request):
    m, y = get_month_year_session(request)
    nm, ny =  move_month(m, y, 1)
    set_month_year_session(request, nm, ny)
    return HttpResponseRedirect(reverse('index', args=[]))



def current_month(request):
    try:
        del request.session['processed_month']
        del request.session['processed_year']
    except:
        pass    
    return HttpResponseRedirect(reverse('index', args=[]))



@login_required
def operation(request): 
    return operation_ex(request, None, None)  
    


@login_required
def operation_ex(request, arrival_form, expense_form): 
    operation_list = Operation.objects.all()

    if arrival_form == None:
        arrival_form = ArrivalForm()
    if expense_form == None: 
        expense_form = ExpenseForm()
  
    processed_month, processed_year = get_month_year_session(request)
        
    context = Context({
        'operation_list': operation_list,
        'arrival_form': arrival_form,
        'expense_form': expense_form,
        'processed_month_verbose': month_verbose[processed_month],
        'processed_month': processed_month,
        'processed_year': processed_year,
    })
    return render_to(request, 'operation.html', context)



@login_required
def new_arrival(request):
    arrival_form = None
    if request.method == 'POST':
        arrival_form = ArrivalForm(request.POST)
        if arrival_form.is_valid():
            processed_month, processed_year = get_month_year_session(request)
            arrival = arrival_form.save(commit = False)
            arrival.kind = 'A'
            arrival.quantity = 1
            arrival.price = arrival.amount
            arrival.special_item = 'no'
            arrival.period_month = processed_month
            arrival.period_year = processed_year
            arrival.save()
            messages.success(request, 'Приход успешно зарегистрировали.')
            return HttpResponseRedirect(reverse('operation', args=[]))
    return operation_ex(request, arrival_form, None)


@login_required
def new_expense(request):
    expense_form = None
    if request.method == 'POST':
        expense_form = ExpenseForm(request.POST)
        if expense_form.is_valid():
            processed_month, processed_year = get_month_year_session(request)
            expense = expense_form.save(commit = False)
            expense.kind = 'E'
            expense.special_item = 'no'
            expense.amount = (expense.quantity * expense.price) * -1
            expense.period_month = processed_month
            expense.period_year = processed_year
            expense.save()
            messages.success(request, 'Расход успешно зарегистрировали.')
            return HttpResponseRedirect(reverse('operation', args=[]))
    return operation_ex(request, None, expense_form)


@login_required
def reg_chop(request):
    if request.method == 'POST':
        try:
            cash = Decimal(request.POST['cash'])
        except:
            messages.warning(request, 'Требуется число.')
            if "prev_request_path" in request.session:
                return HttpResponseRedirect(request.session["prev_request_path"])            
            return HttpResponseRedirect(reverse('index', args=[]))
        processed_month, processed_year = get_month_year_session(request)    
        print processed_month, processed_year
        operation = Operation(kind='A',name='Поступление от ЧОП', quantity='1', price=cash,
                              amount=cash, comment='', special_item='ac', period_year = processed_year, period_month = processed_month)
        operation.save()
        messages.success(request, 'Поступление от ЧОП зарегистрировано.') 
        if "prev_request_path" in request.session:
            return HttpResponseRedirect(request.session["prev_request_path"])        
        return HttpResponseRedirect(reverse('index', args=[]))
    return index(request)


@login_required
@transaction.commit_manually
def reg_concierge_fee(request):
    '''
       Сумма собранная с жильцов + ЧОП + Баланс в журнале прихода расхода
       Если эта сумма больше чем выплата консьержу то
           Регистрация в журнале:
           сумма с жильцов в приход
           Оплата услуг консьержа в расход
       period_year = , period_month = 
    ''' 
    if request.method == 'POST':
        try:
            cash = Decimal(request.POST['cash'])
        except:
            messages.warning(request, 'Требуется число.')
            if "prev_request_path" in request.session:
                return HttpResponseRedirect(request.session["prev_request_path"])
            return HttpResponseRedirect(reverse('index', args=[]))
        processed_month, processed_year = get_month_year_session(request)    
        #
        prev_operation = Operation.objects.filter(period_year=processed_year, period_month=processed_month, special_item='ec').count()
        if prev_operation != 0:
            messages.warning(request, 'В этом месяце оплата услуг уже была.')
            if "prev_request_path" in request.session:
                return HttpResponseRedirect(request.session["prev_request_path"])            
            return HttpResponseRedirect(reverse('index', args=[]))
        # баланс в журнале прихода расхода
        balance = Operation.objects.all().aggregate(Sum("amount"))['amount__sum']
        if balance == None:
            balance = 0
        # Сумма собранная с жильцов
        apartments = MonthlyPayment.objects.filter(year=processed_year, month=processed_month).aggregate(Sum("amount"))  
        if apartments['amount__sum'] == None:
            messages.warning(request, 'Нет ни одного платежа от жильцов.')
            if "prev_request_path" in request.session:
                return HttpResponseRedirect(request.session["prev_request_path"])            
            return HttpResponseRedirect(reverse('index', args=[]))
        apartments = int(apartments['amount__sum'])
        # ЧОП
        chop = Operation.objects.filter(period_year=processed_year, period_month=processed_month, special_item='ac').aggregate(Sum("amount"))
        if chop['amount__sum'] == None:
            messages.warning(request, 'Не было поступления от ЧОП.')
            if "prev_request_path" in request.session:
                return HttpResponseRedirect(request.session["prev_request_path"])            
            return HttpResponseRedirect(reverse('index', args=[]))
        # проверка суммы выплаты консьержу
        if cash > (balance + apartments):
            messages.warning(request, 'У вас нет столько денег.')
            if "prev_request_path" in request.session:
                return HttpResponseRedirect(request.session["prev_request_path"])
            return HttpResponseRedirect(reverse('index', args=[]))
        try:
            operation = Operation(kind='A',name='Собрано с жильцов', quantity='1', price=apartments,
                                  amount=apartments, comment='', special_item='aa', period_year = processed_year, period_month = processed_month)
            operation.save()
            operation = Operation(kind='E',name='Оплата услуг консьержа', quantity='1', price=cash,
                                  amount=(cash * -1), comment='', special_item='ec', period_year = processed_year, period_month = processed_month)
            operation.save()
        except:
            transaction.rollback()
            messages.warning(request, 'Ошибка в транзакции. Операция оплаты услуг не произведена!')
        else:
            transaction.commit()           
            messages.success(request, 'Операция оплаты услуг прошла успешно.') 
        
        if "prev_request_path" in request.session:
            return HttpResponseRedirect(request.session["prev_request_path"])
        return HttpResponseRedirect(reverse('index', args=[]))
    return index(request)

@login_required
def apartment_property(request, apartment_id):
    apartment = Apartment.objects.get(id=apartment_id)
    apartment_payment_list = Payment.objects.filter(apartment=apartment)
    processed_month, processed_year = get_month_year_session(request) 
    if request.method == 'POST':
        form = ApartmentForm(request.POST,instance=apartment) 
        if form.is_valid():
            f = form.save(commit = False)
            f.number = apartment.number
            f.save()
            messages.success(request, 'Изменения сохранены.') 
            return HttpResponseRedirect(reverse('apartment_property', args=[apartment_id,]))
    else:
        form = ApartmentForm(instance=apartment)
    context = Context({
        'apartment':apartment,
        'apartment_payment_list': apartment_payment_list,
        'form':form,
        'processed_month': processed_month,
        'processed_year': processed_year,
        'processed_month_verbose': month_verbose[processed_month],
    })
    return render_to(request, 'apartment_property.html', context)


@login_required
def debtor(request):
    processed_month, processed_year = get_month_year_session(request) 
    qs = MonthlyPayment.objects.filter(year=processed_year, month=processed_month)
    qs.query.group_by = ['house_monthlypayment.apartment_id']
    monthlypayment = qs.annotate(monthly_summ=Sum('amount'))
    apartment_id = [i.apartment.id for i in  monthlypayment if i.monthly_summ == i.apartment.summ] 
    debtors_list = [{'id':i.id, 'number':i.number} for i in Apartment.objects.exclude(summ=0) if i.id not in apartment_id]   
    context = Context({
        'debtors_list':debtors_list,
        'processed_month': processed_month,
        'processed_year': processed_year,
        'processed_month_verbose': month_verbose[processed_month],
    })    
    return render_to(request, 'debtor.html', context)


@login_required
@transaction.commit_manually
def delete_payment(request, id):
    processed_month, processed_year = get_month_year_session(request)
    payment = Payment.objects.get(id=id)
    try:
        payment.monthlypayment_set.all().delete()
        payment.delete()
    except:    
        transaction.rollback()
        messages.warning(request, 'Ошибка в транзакции. Удаление не произведено!')
    else:
        transaction.commit()
        messages.success(request, 'Удалено успешно.')    
 
    if "prev_request_path" in request.session:
        return HttpResponseRedirect(request.session["prev_request_path"])
    return HttpResponseRedirect(reverse('index', args=[]))
    
    
@login_required    
def delete_operation(request, id):
    operation = Operation.objects.get(id=id)
    operation.delete()
    messages.success(request, 'Удалено успешно.')
    if "prev_request_path" in request.session:
        return HttpResponseRedirect(request.session["prev_request_path"])
    return HttpResponseRedirect(reverse('index', args=[]))    
    
    
    